home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / jwpsrc.zip / DICT.C < prev    next >
C/C++ Source or Header  |  1993-03-31  |  21KB  |  748 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3.  
  4. #include "jwp.h"
  5.  
  6. #include "idm.h"
  7.  
  8.  
  9. #define DICTINDENT   5
  10. #define NRCACHE      20
  11.  
  12. typedef struct {
  13.     long int offset;
  14.     KANJI far *string;
  15. } DICTCACHE;
  16.  
  17.  
  18. static BOOL DictOK = FALSE;
  19. static OFSTRUCT dictof, idxof;
  20. static DICTCACHE cache[NRCACHE];
  21.  
  22.  
  23.  
  24.  
  25. static KANJI far *ConvertOffset (int id, LONG lParam, KANJI *buf)
  26. {
  27.     FILE *fp;
  28.     int fd, i, j, ch;
  29.     long int offset;
  30.     int length;
  31.  
  32.     length = (lParam >> 24) & 0x00ff;
  33.     offset = lParam & 0x00ffffff;
  34.  
  35.     /* In the cache? */
  36.  
  37.     for (i = 0; i < NRCACHE; i++) {
  38.         if (cache[i].string == NULL) continue;
  39.         if (cache[i].offset == offset) break;
  40.     }
  41.  
  42.     if (i < NRCACHE) return (cache[i].string);
  43.  
  44.  
  45.     /* Not in the cache */
  46.  
  47.     buf[0] = 0;
  48.  
  49.     fd = OpenFile(NULL, &dictof, OF_READ | OF_REOPEN);
  50.  
  51.     fp = fdopen(fd, "rb");
  52.     if (fp == NULL) {
  53.         close(fd);
  54.         return ((KANJI far *) buf);
  55.     }
  56.  
  57.     fseek(fp, offset, 0);
  58.  
  59.     for (i = j = 0; j < length; i++) {
  60.         ch = getc(fp);
  61.         j++;
  62.  
  63.         if (ch & 0x80) {
  64.             ch &= 0x007f;
  65.             buf[i] = (ch << 8) | (getc(fp) & 0x007f);
  66.             j++;
  67.         } else if (ch == '/') {
  68.             buf[i++] = ',';
  69.             buf[i] = ' ';
  70.         } else {
  71.             buf[i] = ch;
  72.         }
  73.     }
  74.  
  75.     buf[i] = 0;
  76.     fclose(fp);
  77.  
  78.     if (i <= 0) {
  79.         return ((KANJI far *) buf);
  80.     } else if (!ISKANJI(buf[0])) {
  81.         for (; i >= 0; i--) buf[i+DICTINDENT] = buf[i];
  82.         for (i = 0; i < DICTINDENT; i++) buf[i] = ' ';
  83.     } else {
  84.         for (i = 0; buf[i] != 0; i++) {
  85.             if (buf[i] == '[') buf[i] = 0x215a;
  86.             else if (buf[i] == ']') buf[i] = 0x215b;
  87.             else if (buf[i] == ' ') buf[i] = 0x2121;
  88.         }
  89.     }
  90.  
  91.  
  92.     /* Put in the cache */
  93.  
  94.     for (i = 0; i < NRCACHE && cache[i].string != NULL; i++);
  95.     if (i >= NRCACHE) {
  96.         long int diff, maxdiff;
  97.  
  98.         for (i = maxdiff = 0, j = -1; i < NRCACHE; i++) {
  99.             diff = cache[i].offset - offset;
  100.             if (diff < 0) diff = -diff;
  101.             if (diff > maxdiff) {
  102.                 j = i;
  103.                 maxdiff = diff;
  104.             }
  105.         }
  106.         if (j < 0) j = rand() % NRCACHE;
  107.         i = j;
  108.     }
  109.  
  110.     if (cache[i].string != NULL) FreeBlock(cache[i].string);
  111.     cache[i].string = (KANJI far *) BlockAlloc((kanjilen(buf) + 5) * sizeof(KANJI));
  112.     cache[i].offset = offset;
  113.     kanjicpy(cache[i].string, buf);
  114.  
  115.     return ((KANJI far *) buf);
  116. }
  117.  
  118.  
  119.  
  120. static BOOL CheckDictionary (void)
  121. {
  122.     int fd;
  123.     long int indexsize;
  124.     long int dictsize;
  125.  
  126.  
  127.     if (DictOK) return (TRUE);
  128.  
  129.     for (;;) {
  130.         fd = OpenFile(global.jdict, &dictof, OF_READ);
  131.         if (fd >= 0) break;
  132.         if (!RetryMessage ("Cannot open dictionary '%s'!", global.jdict))
  133.             return (FALSE);
  134.     }
  135.     lseek(fd, 0L, 2);
  136.     dictsize = tell(fd);
  137.     close(fd);
  138.  
  139.     for (;;) {
  140.         fd = OpenFile(global.jdictidx, &idxof, OF_READ);
  141.         if (fd >= 0) break;
  142.         if (!RetryMessage ("Cannot open dictionary index '%s'!", global.jdictidx))
  143.             return (FALSE);
  144.     }
  145.  
  146.     lseek(fd, 0L, 0);
  147.     read(fd, &indexsize, sizeof(long int));
  148.     close(fd);
  149.  
  150.     if (indexsize != dictsize + 15) {
  151.         ErrorMessage(global.hwnd, "This index file does not belong to this dictionary!");
  152.         return (FALSE);
  153.     }
  154.  
  155.     DictOK = TRUE;
  156.  
  157.     return (TRUE);
  158. }
  159.  
  160.  
  161.  
  162. static int DictComp (BYTE *p1, BYTE *p2, int n)
  163. {
  164.     int i;
  165.     BYTE c1, c2;
  166.     BOOL f1 = FALSE, f2 = FALSE;
  167.  
  168.     for (i = 0; ; i++, p1++, p2++) {
  169.         if (n > 0 && i >= n) return (0);
  170.  
  171.         c1 = *p1;
  172.         c2 = *p2;
  173.  
  174.         if ('A' <= c1 && c1 <= 'Z') c1 += 32;
  175.         if ('A' <= c2 && c2 <= 'Z') c2 += 32;
  176.  
  177.         if (c1 & 0x80) {
  178.             f1 = !f1;
  179.             if (f1 && c1 == 0xa5) c1 = 0xa4;        /* Katakana? */
  180.         } else {
  181.             f1 = FALSE;
  182.         }
  183.         if (c2 & 0x80) {
  184.             f2 = !f2;
  185.             if (f2 && c2 == 0xa5) c2 = 0xa4;        /* Katakana? */
  186.         } else {
  187.             f2 = FALSE;
  188.         }
  189.  
  190.         if (c1 != c2) return (c1 - c2);
  191.         if (c1 == 0) return (0);
  192.     }
  193.  
  194.     return (c1 - c2);
  195. }
  196.  
  197.  
  198.  
  199. static int SearchDictionary (HWND DlgHwnd, HWND KeyHwnd, HWND ListHwnd)
  200. {
  201.     int i, j, k, last, len;
  202.     int fd, nr_matches;
  203.     BOOL PassedKanji, Duplicate;
  204.     FILE *fp;
  205.     long int nr_index;
  206.     long int top, bottom, middle;
  207.     long int offset, cut, temp;
  208.     int diff, length;
  209.     MSG msg;
  210.     BYTE key[MAXLINELEN], target[MAXLINELEN];
  211.     KANJI ch;
  212.     UNIT far *up;
  213.     RECT rect;
  214.  
  215.  
  216.     /* Deletes everything from the list box */
  217.     if (SendMessage(ListHwnd, LB_GETCOUNT, 0, 0L) > 0)
  218.         SendMessage(ListHwnd, LB_RESETCONTENT, 0, 0L);
  219.  
  220.     while (PeekMessage(&msg, DlgHwnd, 0, 0, PM_REMOVE)) {
  221.         TranslateMessage(&msg);
  222.         DispatchMessage(&msg);
  223.     }
  224.  
  225.  
  226.     /* Opens the dictionary and index files */
  227.  
  228.     fd = OpenFile(NULL, &dictof, OF_READ | OF_REOPEN);
  229.     if (fd < 0) return (0);
  230.  
  231.     fp = fdopen(fd, "rb");
  232.     if (fp == NULL) {
  233.         close(fd);
  234.         return (0);
  235.     }
  236.  
  237.     fd = OpenFile(NULL, &idxof, OF_READ | OF_REOPEN);
  238.     if (fd < 0) {
  239.         fclose(fp);
  240.         return (0);
  241.     }
  242.  
  243.     lseek(fd, 0L, 2);       /* Move to EOF */
  244.  
  245.     nr_index = (tell(fd) / sizeof(long int)) - 1;
  246.     nr_matches = 0;
  247.  
  248.  
  249.     /* Create the key string */
  250.  
  251.     up = (UNIT far *) SendMessage(KeyHwnd, EM_GETLINE, 0, 0L);
  252.  
  253.     for (i = j = 0; ; j++) {
  254.         ch = up[j].kanji;
  255.         if (ch == 0) break;
  256.  
  257.         if (ISKANJI(ch)) {
  258.             key[i++] = HIBYTE(ch) | 0x0080;
  259.             key[i++] = LOBYTE(ch) | 0x0080;
  260.         } else {
  261.             key[i++] = ch;
  262.         }
  263.     }
  264.  
  265.     key[i] = '\0';
  266.     length = i;
  267.  
  268.  
  269.  
  270.     /* Binary Search */
  271.  
  272.     top = 0;
  273.     bottom = nr_index - 1;
  274.  
  275.     for (;;) {
  276.         middle = (top + bottom) / 2;
  277.  
  278.         /* Get the offset */
  279.  
  280.         lseek(fd, (middle + 1) * sizeof(long int), 0);
  281.         read(fd, &offset, sizeof(long int));
  282.  
  283.  
  284.         /* Get the target string */
  285.  
  286.         fseek(fp, offset - 1, 0);
  287.         fgets(target, MAXLINELEN, fp);
  288.  
  289.         diff = DictComp(key, target, -1);
  290.  
  291.         if (diff == 0) {
  292.             cut = middle;
  293.             break;
  294.         }
  295.  
  296.         if (top >= bottom - 1) {
  297.             cut = bottom;
  298.             break;
  299.         }
  300.  
  301.         if (diff > 0) top = middle;
  302.         else bottom = middle;
  303.     }
  304.  
  305.     SendMessage(ListHwnd, WM_SETREDRAW, FALSE, 0L);
  306.     GetClientRect(ListHwnd, &rect);
  307.     rect.right -= 2 * GetSystemMetrics(SM_CXVSCROLL);
  308.  
  309.  
  310.     for (;; cut++) {
  311.         /* Now, did the user abort? */
  312.  
  313.         if (PeekMessage(&msg, DlgHwnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) {
  314.             if (msg.message == WM_CHAR && msg.wParam == '\x1b') {
  315.                 if (YesNo(DlgHwnd, "Dictionary search interrupted!\n\nContinue?") != IDYES) break;
  316.             } else {
  317.                 TranslateMessage(&msg);
  318.             }
  319.             //DispatchMessage(&msg);
  320.         }
  321.  
  322.         lseek(fd, (cut + 1) * sizeof(long int), 0);
  323.         read(fd, &offset, sizeof(long int));
  324.  
  325.         /* Get the text string */
  326.  
  327.         offset--;
  328.         fseek(fp, offset, 0);
  329.         fgets(target, MAXLINELEN, fp);
  330.  
  331.  
  332.         /* Still matches? */
  333.  
  334.         if (DictComp(key, target, length)) break;
  335.         nr_matches++;
  336.  
  337.         if (nr_matches > 0) {
  338.             char tempbuf[50];
  339.  
  340.             sprintf(tempbuf, "%d match%s", nr_matches, (nr_matches > 1) ? "es" : "");
  341.             SetDlgItemText(GetParent(KeyHwnd), 4202, tempbuf);
  342.         }
  343.  
  344.  
  345.         /* OK, now backseek to the beginning of the line, shall we? */
  346.  
  347.         fseek(fp, offset, 0);
  348.  
  349.         for (;;) {
  350.             if (offset < MAXLINELEN) {
  351.                 fseek(fp, 0L, 0);
  352.                 j = offset;
  353.                 offset = 0L;
  354.             } else {
  355.                 fseek(fp, -MAXLINELEN, 1);      /* Get the previous block */
  356.                 j = MAXLINELEN;
  357.                 offset -= MAXLINELEN;
  358.             }
  359.             fread